/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include <向量.h>

#include "core/属性.h"


/*inline void f_get摄像机矩阵(float32* mat, const vec3& 摄像机位置, const vec3& 视点, const vec3& 上方向) {
	//float32 mat[16];
	auto 临时mat = DirectX::XMMatrixLookAtLH(DirectX::XMVectorSet(摄像机位置.x, 摄像机位置.y, 摄像机位置.z, 1),
		DirectX::XMVectorSet(视点.x, 视点.y, 视点.z, 1),
		DirectX::XMVectorSet(上方向.x, 上方向.y, 上方向.z, 1)
	).r;

	memcpy(mat, 临时mat, sizeof(float32) * 16);
	
}*/

EngineAPI_EXPORT int8 f_random_I8(ivec2 区间, int32 种子);
EngineAPI_EXPORT void f_random_I8Array(S_I8Array* val, uint64 num, int8 最小, int8 最大, int32 种子);
EngineAPI_EXPORT void f_random_F32Array(S_F32Array* vec, uint64 num, float32 最小, float32 最大, int32 种子);
EngineAPI_EXPORT void f_random_I32Array(S_I32Array* vec, uint64 num, float32 最小, float32 最大, int32 种子);
EngineAPI_EXPORT void f_random_UI32Array(S_UI32Array* vec, uint64 num, uint32 最小, uint32 最大, int32 种子);

EngineAPI_EXPORT void f_random_Vec3Array(S_Vec3Array* vec, uint64 num, vec2 X, vec2 Y, vec2 Z, int32 种子);
EngineAPI_EXPORT void f_random_iVec2Array(S_iVec2Array* vec, uint64 num, const ivec2& X区间, const ivec2& Y区间, int32 种子, uint8 type);
EngineAPI_EXPORT void f_random_iVec3Array(S_iVec3Array* vec, uint64 num, const ivec3& 最小, const ivec3& 最大, int32 种子);




EngineAPI_EXPORT mat3X3	f_get坐标集包围盒(vec3* v, uint32 num);
EngineAPI_EXPORT float32	f_get坐标集包围球(vec3* v, uint32 num);


EngineAPI_EXPORT vec3 f_math_向量归一化(const vec3& dirA, uint8 type);
EngineAPI_EXPORT void f_math_向量归一化m(const S_Vec3Array* dirA, S_Vec3Array* r, uint8 type);

EngineAPI_EXPORT float32 f_math_两向量标量(const vec3& dirA, const vec3& dirB, uint8 type);
EngineAPI_EXPORT void f_math_两向量标量m(const S_Vec3Array* dirA, const S_Vec3Array* dirB, S_F32Array* r, uint8 type);

EngineAPI_EXPORT vec3 f_math_两向量叉积(const vec3& dirA, const vec3& dirB);
EngineAPI_EXPORT void f_math_两向量叉积m(const S_Vec3Array* dirA, const S_Vec3Array* dirB, S_Vec3Array* r);

EngineAPI_EXPORT void f_math_向量长度m(S_F32Array* r, const S_Vec3Array* dirA, uint8 type);

EngineAPI_EXPORT vec4 f_math_quat两向量(const vec3& dirA, const vec3& dirB);
EngineAPI_EXPORT void f_math_quat两向量m(const S_Vec3Array* dirA, const S_Vec3Array* dirB, S_Vec4Array* r);
EngineAPI_EXPORT void f_math_quat以轴向和角度构建m(S_Vec4Array* quat, const S_Vec3Array* v, const S_F32Array* a);

EngineAPI_EXPORT void f_math_quat相乘m(const S_Vec4Array* dirA, const S_Vec4Array* dirB, S_Vec4Array* r);

EngineAPI_EXPORT void f_math_quat变换m(const S_Vec3Array* dirA, const S_Vec4Array* dirB, S_Vec3Array* r, int32 方式);
EngineAPI_EXPORT void f_math_四元数转欧拉角m(const S_Vec4Array* quat, S_Vec3Array* r);
EngineAPI_EXPORT void f_math_四元数转3X3矩阵m(const S_Vec4Array* quat, S_Mat33Array* r);
EngineAPI_EXPORT void f_math_四元数转4X4矩阵m(const S_Vec4Array* quat, S_Mat44Array* r);

EngineAPI_EXPORT vec3 f_math_轴向旋转变换(vec3 point, vec3 轴向, float32 角度, int32 方式);
EngineAPI_EXPORT void f_math_轴向旋转变换m(S_Vec3Array* 新坐标, const S_Vec3Array* point, const S_Vec3Array* 轴向, S_F32Array* r, int32 方式);


EngineAPI_EXPORT void f_math_mat44_变换m(const S_Vec3Array* dirA, const S_Mat44Array* dirB, S_Vec3Array* r);
EngineAPI_EXPORT void f_math_mat44_相乘m(const S_Mat44Array* dirA, const S_Mat44Array* dirB, S_Mat44Array* r);
EngineAPI_EXPORT Mat44f f_math_mat44_相乘(const Mat44f& dirA, const Mat44f& dirB);


EngineAPI_EXPORT vec3 f_math_绕点旋转(const vec3& point, const vec3& 轴向, const float32 弧度, const vec3& 中心);
EngineAPI_EXPORT void f_math_绕点旋转m(S_Vec3Array* r, const S_Vec3Array* point, const S_Vec3Array* 轴向, const S_F32Array* 弧度, const vec3& 中心);



EngineAPI_EXPORT void f_mat_平面构建(const S_Vec3Array* point, S_Vec4Array* plane);
EngineAPI_EXPORT void f_mat_点到平面距离(const S_Vec3Array* point, const S_Vec4Array* plane, S_F32Array* 距离);
EngineAPI_EXPORT void f_mat_射线平面相交(const S_Vec3Array* point, const S_Vec4Array* plane, S_Vec3Array* 交点);






EngineAPI_EXPORT void f_math_视锥平面计算(const Mat44f& mat, vec4 planes[6]);

EngineAPI_EXPORT vec3 f_mat_点统计v3(const S_Vec3Array* point, const S_Props* 计算方式);
EngineAPI_EXPORT vec2 f_mat_点统计v2(const S_Vec2Array* point, const S_Props* 计算方式);

void f_math_Cube相机矩阵(vec3 pos, Mat44f mat[6]);



Inline S_Bounding f_bounding_组合(const S_Bounding& b1, const S_Bounding& b2) {
	return {
		vec_Min(b1.min, b2.min),
		vec_Max(b1.max, b2.max),
	};
}

Inline S_Sphere f_graph_取三角形球形包围(const vec3& PointA, const vec3& PointB, const vec3& PointC) {
	S_Sphere s;
	s.pos = { (PointA.x + PointB.x + PointC.x) / 3.0f,
				(PointA.y + PointB.y + PointC.y) / 3.0f,
				(PointA.z + PointB.z + PointC.z) / 3.0f
	};

	s.radius = vec_len(s.pos - PointA);
	s.radius = DEF_Max(s.radius, vec_len(s.pos - PointB));
	s.radius = DEF_Max(s.radius, vec_len(s.pos - PointC));

	return s;
}

EngineAPI_EXPORT S_Sphere f_graph_取三角形球形包围(vec3* 三角形);







// 光线与圆球求交
Inline float32 f_射线与点相交(const vec3& rayO, const vec3& rayD, const S_Sphere& sphere) {
	vec3 oc = rayO - sphere.pos;

	float32 a = vec_dot(oc, oc);
	float32 b = 2.0 * vec_dot(oc, rayD);

	float32 c = a - sphere.radius * sphere.radius;
	float32 h = b * b - 4.0 * c;
	if (h < 0.0) {
		return -1.0;
	}
	float32 t = (-b - sqrt(h)) / (2.0);

	return t;
}

Inline float32 f_双向射线与点相交(const vec3& rayO, const vec3& rayD, const S_Sphere& sphere) {
	vec3 oc = rayO - sphere.pos;

	float32 a = vec_dot(oc, oc);
	float32 c = a - sphere.radius * sphere.radius;

	float32 b = 2.0 * vec_dot(oc, rayD);

	float32 h = b * b - 4.0 * c;
	return (-b - sqrt(fabs(h))) / (2.0);

	if (h < 0.0) {

		b = 2.0 * vec_dot(oc, vec_反向(rayD));
		h = b * b - 4.0 * c;

		if (h < 0.0) return -1.0;
	}

	a = (-b - sqrt(h)) / (2.0);
	return a;
}


Inline float32 f_直线到点的距离(const vec3& rayO, const vec3& 单位向量, const S_Sphere& sphere) {
	vec3 oc = sphere.pos - rayO;
	float32 斜边长度 = vec_len(oc);

	float64 直角边长度 = 斜边长度 * 斜边长度 - sphere.radius * sphere.radius;
	直角边长度 = sqrt(abs(直角边长度));

	vec3 射线点 = 单位向量 * float32(直角边长度) + rayO;
	float32 检测距离A = vec_len(射线点 - sphere.pos);

	float32 距离A = sphere.radius - 检测距离A;
	if (距离A < 0) {
		射线点 = rayO - 单位向量 * 直角边长度;
		检测距离A = vec_len(射线点 - sphere.pos);

		return sphere.radius - 检测距离A;
	}
	return 距离A;




	float32 a = vec_dot(oc, oc);
	float32 b = 2.0 * vec_dot(oc, 单位向量);

	float32 c = a - sphere.radius * sphere.radius;
	float32 h = b * b - 4.0 * c;

	float32 t = (-b - sqrt(fabs(h))) / (2.0);
	return t;
}

EngineAPI_EXPORT void f_随机向量(std::vector<S_Sphere>& vec, uint64 num, const S_Sphere& 最小, const S_Sphere& 最大, int32 种子);


Inline void operator+=(std::vector<S_VNT1>& a, const vec3 b) {
	for (auto& e : a) {
		e.vert += b;
	}
}
Inline void operator-=(std::vector<S_VNT1>& a, const vec3 b) {
	for (auto& e : a) {
		e.vert -= b;
	}
}
Inline void operator*=(std::vector<S_VNT1>& a, const vec3 b) {
	for (auto& e : a) {
		e.vert *= b;
	}
}
Inline void operator/=(std::vector<S_VNT1>& a, const vec3 b) {
	for (auto& e : a) {
		e.vert /= b;
	}
}
Inline void operator*=(std::vector<S_VNT1>& a, const vec4 b) {
	for (auto& e : a) {
		e.vert = f_graph_quatTranformInv(b, e.vert);
	}
}


Inline std::vector<float32> operator*(const std::vector<float32>& a, const float32 b) {
	std::vector<float32> c = a;
	for (auto& e : c) {
		e *= b;
	}
	return c;
}

Inline void operator+=(std::vector<uint32>& a, const uint32 b) {
	for (auto& e : a) {
		e += b;
	}
}

Inline void operator+=(std::vector<vec2>& a, const float32 b) {
	for (auto& e : a) {
		e += b;
	}
}

Inline void operator+=(std::vector<vec2>& a, const vec2& b) {
	for (auto& e : a) {
		e += b;
	}
}

Inline void operator-=(std::vector<vec2>& a, const vec2& b) {
	for (auto& e : a) {
		e -= b;
	}
}

Inline void operator*=(std::vector<vec2>& a, const std::vector<float32> b) {
	uint32 num = a.size();
	for (uint32 i = 0; i < num; ++i) {
		a[i] += b[i];
	}
}

Inline void operator/=(std::vector<vec2>& a, const float32 b) {
	for (auto& e : a) {
		e /= b;
	}
}

Inline void operator+=(std::vector<vec3>& a, const vec3& b) {
	for (auto& e : a) {
		e += b;
	}
}

Inline void operator+=(std::vector<S_VNTC>& a, const vec3& b) {
	for (auto& e : a) {
		e.vert += b;
	}
}
Inline void operator*=(std::vector<S_VNTC>& a, const vec3& b) {
	for (auto& e : a) {
		e.vert *= b;
	}
}


Inline vec2 f_mat_圆坐标(const vec2& 中心, float32 半径, float32 i) {
	vec2 结果;
	结果.x = 中心.x + cos(float32(M_角度转弧度(i))) * 半径;
	结果.y = 中心.y + sin(float32(M_角度转弧度(i))) * 半径;
	return 结果;
}


Inline mat3 f_math_tranform(vec2 loc, vec2 scal = {1,1}, vec2 rot = {0,0}) {
	mat3 mat = f_mat3x3_Identity();
	mat *= f_mat3x3_Location(loc);
	mat *= f_mat3x3_Scale(scal);
	
	return mat;
}


int32 f_meth_刻度缩放(float32& 跨度, float32 scale, int32 细分 = 5, int32 进制 = 2);


